﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.IO;
using System.ComponentModel;

namespace CopyCameraFiles
{
    public delegate void FileFoundHandler(object sender, EventArgs e);
    
    public class FileFinder
    {
        public event FileFoundHandler FileFound;

        protected virtual void OnFileFound(object sender, EventArgs e)
        {
            FileFoundHandler handler = FileFound;
            if (FileFound != null)
                FileFound(this, e);
        }

        public FileFinder()
        {
            // default implementation, likely to be overwritten by user
            Path = Environment.GetFolderPath(Environment.SpecialFolder.MyComputer);
            Pattern = "*";
            DirectorySearchOption = SearchOption.TopDirectoryOnly;
            fileInfoList = new List<FileInfo>();
        }
        
        private List<FileInfo> fileInfoList;
        public string Path { get; set; }
        public string Pattern { get; set; }
        public SearchOption DirectorySearchOption { get; set; }
        public int FileCount
        {
            get { return fileInfoList.Count; }
        }

        public List<FileInfo> GetFileInfoList()
        {
            return fileInfoList;
        }

        public void StartFindFiles(BackgroundWorker worker, string path)
        {
            if (string.IsNullOrEmpty(Path) || !Directory.Exists(path)) return;

            // determine to include subfolders in search
            if (DirectorySearchOption == SearchOption.AllDirectories)
            {   
                FindFilesRecursively(worker, path);
            }
            else
            {
                FindFilesInCurrentDir(worker, path);
            }
        }

        private void FindFilesInCurrentDir(BackgroundWorker worker, string path)
        {
            if (string.IsNullOrEmpty(path) || !Directory.Exists(path)) return;

            foreach (var file in Directory.GetFiles(path, Pattern))
            {
                try
                {
                    fileInfoList.Add(new FileInfo(file));
                    OnFileFound(FileCount, EventArgs.Empty);
                    if (worker.CancellationPending)
                        return;
                }
                catch (Exception)
                {
                    
                    throw;
                }
                
            }
        }

        private void FindFilesRecursively(BackgroundWorker worker, string path)
        {
            if (string.IsNullOrEmpty(path) || !Directory.Exists(path)) return;
            
            var dirs = Directory.GetDirectories(path);
            
            // find files directly in this folder if no subfolders exist 
            if (dirs.Length == 0) FindFilesInCurrentDir(worker, path);
            
            foreach (var dir in dirs)
            {
                try
                {
                    FindFilesInCurrentDir(worker, dir);
                }
                catch (UnauthorizedAccessException)
                {
                    //skip folder and continue
                    continue;
                }
                catch (PathTooLongException)
                {
                    //skip and continue
                    continue;
                }
                FindFilesRecursively(worker, dir);
            }
        }

        private void AddFileInfoToList(string[] filePaths)
        {
            foreach (var path in filePaths)
            {
                fileInfoList.Add(new FileInfo(path));
                OnFileFound(FileCount,EventArgs.Empty);
            }
        }

        public void ClearFileList()
        {
            fileInfoList.Clear();
        }
    }
}
